package ks.client.lobby;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;


import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import ks.client.UserContext;
import ks.client.game.GameManager;
import ks.client.interfaces.ILobby;
import ks.client.interfaces.ILobbyInitialize;
import ks.client.ipc.Client;
import ks.client.processor.ClientProcessor;
import ks.framework.interfaces.IConnectionHandler;

/**
 * Primary KS client frontEnd that acts as the central hub for much of the
 * client-side behavior.
 * <p>
 * From the lobby you can always get the UserContext.
 * <p>
 * @author George Heineman
 */
public class LobbyFrame extends JFrame implements IConnectionHandler, ILobby {
	// keep eclipse happy
	private static final long serialVersionUID = 1L;

	// my GUI
	LobbyPanel inner;

	// my menu bar.
	JMenuBar menu;
	
	/** User context for connection information. */
	UserContext context;

	/** Callback for connected status. */
	ILobbyInitialize lobbyCallback;
	
	/**
	 * Each lobby must have a context in which to operate.
	 */
	public LobbyFrame(UserContext context) {
		this.context = context;
		
		// prepare 
		initialize();
	}
	
	/**
	 * Initialize GUI elements of this component.
	 */
	private void initialize() {
		inner = new LobbyPanel(this);
		setContentPane(inner);
		setTitle("Sample KS frontend");
		setSize(850, 750);
		setMinimumSize(new Dimension(600, 420));

		setJMenuBar(getKSMenuBar());
		
		setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);

		addWindowListener(new WindowAdapter() {
			
			@Override
			public void windowClosing(WindowEvent we) {

				int selection = JOptionPane.showConfirmDialog(null,
						"Are you sure you want exit?", "Kombat Games",
						JOptionPane.YES_NO_OPTION,
						JOptionPane.WARNING_MESSAGE);
				if( selection == JOptionPane.YES_OPTION ) {
					tryToDisconnect();
					setVisible(false);
					dispose();
				} else {
					inner.append("Thank goodness you came to your senses!");
				}
			}
		});
	}

	/**
	 * Get or create the menu bar for the LobbyFrame
	 * @return
	 */
	public JMenuBar getKSMenuBar() {
		if (menu == null) {
			menu = new JMenuBar();
			
			// create default
			JMenu ksg = new JMenu("KombatGames");
			menu.add(ksg);
			
			JMenuItem about = new JMenuItem("About...");
			ksg.add(about);
			
			about.addActionListener(new ActionListener() {


				@Override
				public void actionPerformed(ActionEvent e) {
					System.err.println ("ABOUT goes here...");				
				}
				
			});
			
		}
		
		return menu;
	}

	/**
	 * Respond to changes in our connected status
	 * 
	 * @param status
	 */
	public void connected(boolean status) {
		inner.getLobbyInput().setEditable(status);

		// update connect
		if (status) {
			// now that we are connected we can set up the processor
			// for all requests coming back from the server
			Client client = context.getClient();
			client.setProcessor(new ClientProcessor(this));
		}
		
		// make sure we tell our lobby initializer.
		if (lobbyCallback != null) {
			lobbyCallback.connected(status);
		}
	}

	/**
	 * Try to disconnect from remote server.
	 * <p>
	 * If client not yet connected (because client is null) then return true
	 * since that is ok.
	 */
	public boolean tryToDisconnect() {
		Client client = context.getClient();
		if (client == null) { return true; }

		// close down games, if any in progress...
		GameManager.instance().exitGameWindow();
		
		if (!client.disconnect()) {
			return false;
		}

		return true;
	}

	/**
	 * Append string to RoomGUI output.
	 * 
	 * @param s
	 */
	public void append(String s) {
		inner.append(s);
	}

	@Override
	public UserContext getContext() {
		return context;
	}

	/** Expose inner lobby panel, mostly for testing. */
	public LobbyPanel getInnerPanel() {
		return inner;
	}

	public void setTableManagerGUI(JPanel tableManagerGUI) {
		inner.setTableManagerGUI(tableManagerGUI);
	}

	public void setUserManagerGUI(JPanel userManagerGUI) {
		inner.setUserManagerGUI(userManagerGUI);
	}

	@Override
	public JPanel getTableManagerGUI() {
		return inner.getTableManagerGUI();
	}

	@Override
	public JPanel getUserManagerGUI() {
		return inner.getUserManagerGUI();
	}

	/**
	 * Need to have frame know of the initialization callback.
	 * @param lobbyCallback
	 */
	public void setLobbyInitialization(ILobbyInitialize lobbyCallback) {
		this.lobbyCallback = lobbyCallback;
	}
}
